package cn.zhz.privacy.handler;

import cn.zhz.privacy.annotation.FieldEncrypt;
import cn.zhz.privacy.crypto.ICrypto;
import cn.zhz.privacy.enums.SerializeType;
import cn.zhz.privacy.properties.CryptoProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ZHZ
 * @since 2023-03-07
 */
@Slf4j
public class CryptHandler extends AbstractHandler<FieldEncrypt> implements ApplicationContextAware {

    private ApplicationContext applicationContext;
    private static final Map<Class<?>, List<Field>> FIELDS_CACHE = new ConcurrentHashMap<>();
    private final CryptoProperties cryptoProperties;

    public CryptHandler(CryptoProperties cryptoProperties) {
        super(FieldEncrypt.class);
        this.cryptoProperties = cryptoProperties;
    }

    protected Map<Class<?>, List<Field>> getFieldCache() {
        return FIELDS_CACHE;
    }

    @Override
    String getAfterValue(FieldEncrypt annotation, String originalValue, SerializeType serializeType) {
        //全局配置的key
        String key = cryptoProperties.getKey();
        ICrypto iCrypto = applicationContext.getBean(annotation.algorithm().name(),ICrypto.class);

        String valueResult;
        try {
            if (serializeType.equals(SerializeType.DECRYPT)) {
                valueResult = iCrypto.decrypt(String.valueOf(originalValue), key);
            } else {
                valueResult = iCrypto.encrypt(String.valueOf(originalValue), key);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return valueResult;
    }


    /**
     * 出参解密
     *
     * @param resultList
     */
    @Override
    public void handleResultList(List<Object> resultList) {
        if (resultList == null && resultList.isEmpty()) {
            return;
        }
        resultList.forEach(object -> {
            if (object != null) {
                handleObject(object, object.getClass(), SerializeType.DECRYPT);
            }
        });
    }


    /**
     * 入参加密
     *
     * @param parameter
     */
    @Override
    public void handleParam(Object parameter) {
        if (parameter == null) {
            return;
        }
//        if (parameter instanceof Map) {
//            Map paramMap = (Map) parameter;
//            Set<Object> handledObjectList = new HashSet<>();
//            for (Object value : paramMap.values()) {
//                if (value != null) {
//                    if (value instanceof Collection) {
//                        for (Object item : ((Collection<?>) value)) {
//                            if (handledObjectList.contains(item)) {
//                                continue;
//                            }
//                            //parse(item.getClass());
//                            handleObject(item, item.getClass(), SerializeType.ENCRYPT);
//                            handledObjectList.add(item);
//                        }
//                    } else {
//                        //parse(value.getClass());
//                        handleObject(value, value.getClass(), SerializeType.ENCRYPT);
//                    }
//                }
//            }
//
//        } else {
            handleObject(parameter, parameter.getClass(), SerializeType.ENCRYPT);
//        }
    }

//    /**
//     * 处理参数或结果
//     *
//     * @param object
//     * @param serializeType
//     */
//    protected void handleParameterOrResult(Object object, SerializeType serializeType) {
//        //多个参数
//        if (object instanceof Map) {
//            Map paramMap = (Map) object;
//            Set keySet = paramMap.keySet();
//            for (Object key : keySet) {
//                Object o = paramMap.get(key);
//                // 如果参数是集合类型，根据遍历处理
//                if (o != null) {
//                    if (o instanceof Collection) {
//                        for (Object item : ((Collection<?>) o)) {
//                            parse(item.getClass());
//                            handleObject(item, item.getClass(), serializeType);
//                        }
//                    } else {
//                        //
//                        parse(o.getClass());
//                        handleObject(o, o.getClass(), serializeType);
//                    }
//                }
//            }
//        } else {
//            if (object != null) {
//                //
//                parse(object.getClass());
//                handleObject(object, object.getClass(), serializeType);
//            }
//        }
//
//    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
